#ifndef _CERE_SOLVE_
#define _CERE_SOLVE_

#include <QPointF>

#include <ceres/ceres.h>
#include <chrono>
#include <QVector>

// 代价函数的计算模型
struct CURVE_FITTING_COST
{
    CURVE_FITTING_COST ( double x, double y ) : _x ( x ), _y ( y ) {}
    // 残差的计算
    template <typename T>
    bool operator() (
        const T* const abc,     // 模型参数，有3维
        T* residual ) const     // 残差
    {
        residual[0] = (_x - abc[0]) * (_x - abc[0]) + (_y - abc[1]) * (_y - abc[1]) - abc[2] * abc[2];
        return true;
    }
    const double _x, _y;    // x,y数据
};


int solveCircleFitting(const QVector<QPointF> data,double *abc)
{
    // 构建最小二乘问题
    ceres::Problem problem;
    for ( int i=0; i<data.size(); i++ )
    {
        problem.AddResidualBlock (     // 向问题中添加误差项
        // 使用自动求导，模板参数：误差类型，误差维度，输入维度，维数要与前面struct中一致
            new ceres::AutoDiffCostFunction<CURVE_FITTING_COST, 1, 3> (
                new CURVE_FITTING_COST ( data[i].x(), data[i].y() )
            ),
            nullptr,            // 核函数，这里不使用，为空
            abc                 // 待估计参数
        );
    }

    // 配置求解器
    ceres::Solver::Options options;     // 这里有很多配置项可以填
    options.linear_solver_type = ceres::DENSE_QR;  // 增量方程如何求解
    options.minimizer_progress_to_stdout = true;   // 输出到cout

    ceres::Solver::Summary summary;                // 优化信息
    std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
    ceres::Solve ( options, &problem, &summary );  // 开始优化
    std::chrono::steady_clock::time_point t2 = std::chrono::steady_clock::now();
    std::chrono::duration<double> time_used = std::chrono::duration_cast<std::chrono::duration<double>>( t2-t1 );
    std::cout <<"solve time cost = "<< time_used.count() <<" seconds. "<< std::endl;
}



#endif
